package com.example.factory.core.repository.impl;

import com.example.factory.core.domain.Equipment;
import com.example.factory.core.repository.EquipmentRepositoryCustom;
import com.example.factory.core.repository.query.EquipmentListQueryParams;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.util.StringUtils;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

/**
 * @author Lei Tao
 */
public class EquipmentRepositoryImpl implements EquipmentRepositoryCustom {
    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public Page<Equipment> findEquipments(EquipmentListQueryParams queryParams) {
        Query query = buildQuery(true, queryParams);
        Long total = (Long) query.getSingleResult();
        query = buildQuery(false, queryParams);
        Pageable pageable = queryParams.pageable();
        return new PageImpl<Equipment>(query.getResultList(), pageable, total);
    }

    private Query buildQuery(boolean forCount, EquipmentListQueryParams queryParams) {
        String hql = "select e from Equipment e where e.archived = false";
        if (forCount) {
            hql = "select count(e.id) from Equipment e where e.archived = false";
        }

        String departmentName = queryParams.departmentName();
        String equipmentType = queryParams.equipmentType();
        String name = queryParams.name();
        if (!StringUtils.isEmpty(departmentName)) {
            hql += " and e.department.name = :departmentName";
        }
        if (!StringUtils.isEmpty(name)) {
            hql += " and e.name = :name";
        }
        if (!StringUtils.isEmpty(equipmentType)) {
            hql += " and e.equipmentType = :equipmentType";
        }
        Pageable pageable = queryParams.pageable();
        Query query = entityManager.createQuery(hql);
        if (hql.contains(":departmentName")) {
            query.setParameter("departmentName", departmentName);
        }
        if (hql.contains(":name")) {
            query.setParameter("name", name);
        }
        if (hql.contains(":equipmentType")) {
            query.setParameter("equipmentType", equipmentType);
        }
        if (!forCount) {
            query.setFirstResult((int) pageable.getOffset());
            query.setMaxResults(pageable.getPageSize());
        }
        return query;
    }
}
